package com.test.web3j.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.concurrent.TimeUnit;

import org.bitcoinj.core.Address;
import org.bitcoinj.core.BlockChain;
import org.bitcoinj.core.Coin;
import org.bitcoinj.core.ECKey;
import org.bitcoinj.core.InsufficientMoneyException;
import org.bitcoinj.core.NetworkParameters;
import org.bitcoinj.core.PeerGroup;
import org.bitcoinj.net.discovery.DnsDiscovery;
import org.bitcoinj.store.BlockStoreException;
import org.bitcoinj.store.SPVBlockStore;
import org.bitcoinj.wallet.KeyChain;
import org.bitcoinj.wallet.UnreadableWalletException;
import org.bitcoinj.wallet.Wallet;
import org.bitcoinj.wallet.WalletProtobufSerializer;

import com.google.common.util.concurrent.MoreExecutors;

/**
 * 比特币工具类
 */
public class BtcUtil {
	
	private static String blockFileAddress = "D:/tmp/bitcoin-blocks";
	
	/**
	 * 通过ECKey创建钱包
	 * @return 钱包对象
	 */
	public Wallet newWallet(NetworkParameters params, ECKey key) {
		Wallet wallet = new Wallet(params);
        wallet.importKey(key);
        return wallet;
	}
	
	/**
	 * 从文件夹中加载钱包
	 * @param filePath
	 * @return
	 */
	public Wallet getWallet(String filePath) {
		Wallet wallet = null;
		try {
			// 读取指定路径钱包文件
			File walletFile = new File(filePath);
			if (walletFile.exists()) {
				InputStream inputStream = new FileInputStream(walletFile);
				//反序列列化
				wallet = new WalletProtobufSerializer().readWallet(inputStream);
				//设置自动保存
				wallet.autosaveToFile(walletFile, 3 * 1000, TimeUnit.MILLISECONDS, null);
				//清理钱包
				wallet.cleanup();
			}
		} catch (UnreadableWalletException e) {
			e.printStackTrace();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
		return wallet;
	}
	
	/**
	 * 获取钱包地址
	 * @param wallet
	 * @param keyPurpose
	 * @return 钱包地址
	 */
	public Address getWalletAddress(Wallet wallet, KeyChain.KeyPurpose keyPurpose) {
		Address address = wallet.currentAddress(keyPurpose);
		return address;
	}
	
	/**
	 * 查询钱包余额
	 * @param wallet
	 * @param balanceType
	 * @return
	 */
	public Coin getBalance(Wallet wallet, Wallet.BalanceType balanceType) {
		Coin balance = wallet.getBalance(balanceType);
		return balance;
	}
	
	
	/**
	 * 支付比特币
	 * @param params
	 * @param wallet
	 * @param toAddress
	 * @param amountToSend
	 */
	@SuppressWarnings("deprecation")
	public void payBitCoin(NetworkParameters params, Wallet wallet, String toAddressStr, Coin amountToSend) {
		// 设置接收方的地址
		Address toAddress = Address.fromBase58(params, toAddressStr);
		
        try {
        	// 接入流通网络并下载比特币区块
        	File blockFile = new File(blockFileAddress);
			SPVBlockStore blockStore = new SPVBlockStore(params, blockFile);
			BlockChain blockChain = new BlockChain(params, wallet, blockStore);
	        PeerGroup peerGroup = new PeerGroup(params, blockChain);
	        peerGroup.addPeerDiscovery(new DnsDiscovery(params));
	        peerGroup.addWallet(wallet);
	        
	        // 给目的账户发送指定数量的比特币
	        Wallet.SendResult sendResult = wallet.sendCoins(peerGroup, toAddress, amountToSend);
	     
	        // 设置交易完成后的事件响应
			sendResult.broadcastComplete.addListener(new Runnable() {
				@Override
				public void run() {
					System.out.println("Coins Sent! Transaction hash is " + sendResult.tx.getHashAsString());
					// TODO：交易完成之后要做的事情
				}
			}, MoreExecutors.sameThreadExecutor());
		} catch (BlockStoreException e) {
			e.printStackTrace();
		} catch (InsufficientMoneyException e) {
			e.printStackTrace();
		}
	}
}
